﻿/*************************************
 * Creator:SunnyPaine
 * DateTime:2022/8/22 15:21:52
 * Description:<Description>
 * CopyRight:
 * ***********************************/

using Autofac;
using SunnyPaine.Autofac.Extension.Stereotype.Entities;
using SunnyPaine.Autofac.Extension.Stereotype.Selector;
using SunnyPaine.SqlSugar.Autofac.Stereotype.Selector;
using System;
using System.Collections.Generic;
using System.Linq;

namespace SunnyPaine.Autofac.Extension.Stereotype
{
    /// <summary>
    /// 注入。
    /// </summary>
    public static class Injecter
    {
        /// <summary>
        /// 扫描完成的实例信息。
        /// </summary>
        public static List<InstanceInfo> InstanceInfos { get; private set; }
        /// <summary>
        /// 
        /// </summary>
        public static bool UseInterfaceInject { get; private set; }


        /// <summary>
        /// 启用自动注册实例。
        /// </summary>
        /// <param name="builder">Autofac容器。</param>
        /// <param name="useInterfaceInject">是否使用接口标记。
        /// <para>true：autofac进行自动扫描与注册实例时，只会对被标记的的接口进行实例化或引用。</para>
        /// <para>false：autofac进行自动扫描与注册实例时，将对类所有实现的接口（包括父级接口）进行实例化或引用。</para>
        /// </param>
        public static void UseAutoRegister(this ContainerBuilder builder, bool useInterfaceInject = false)
        {
            Scanner scanner = new Scanner(useInterfaceInject);
            InstanceInfos = scanner.Scan();
            UseInterfaceInject = useInterfaceInject;
            //Register(builder);
        }

        /// <summary>
        /// 当Build后执行。
        /// </summary>
        /// <param name="container">Autofac容器。</param>
        /// <param name="buildAfters">执行 ContainerBuilder.Build() 方法后，要执行的事情。</param>
        public static void BuildAfter(this IContainer container, params IBuildAfter[] buildAfters)
        {
            foreach (IBuildAfter item in buildAfters)
            {
                item.Execute(container);
            }
        }

        /// <summary>
        /// 注册实例。
        /// </summary>
        /// <param name="builder"></param>
        public static void Register(this ContainerBuilder builder)
        {
            //需要强调关于Autofac注册类型时，默认使用 Transit 生命周期，表示每次请求时都会创建一个新的实例：
            //builder.Register<MyType>;
            //builder.Register<MyType>().As<IMyType>();
            //builder.Register<MyType>().As<IMyType>().Named<IMyType>("name");
            //除非明确指明单例生命周期：
            //builder.RegisterType<MyType>().As<IMyType>().SingleInstance();

            List<InstanceInfo> iis = InstanceInfos.OrderBy(p => p.Sort).ToList();
            foreach (InstanceInfo ii in iis)
            {
                if (ii.ComponentType == ComponentType.Configure)
                {
                    var registrationBuilder = builder.Register(c => ii.Instance);
                    foreach (Type typeInterface in ii.InterfaceTypes)
                    {
                        registrationBuilder.Named(ii.Name, typeInterface).As(typeInterface);
                    }
                    if (ii.Single)
                    {
                        registrationBuilder.SingleInstance();
                    }
                }
                else
                {
                    if (ii.ImplementType.IsGenericType)//泛型
                    {
                        var registrationBuilder = builder.RegisterGeneric(ii.ImplementType);
                        foreach (Type typeInterface in ii.InterfaceTypes)
                        {
                            registrationBuilder.Named(ii.Name, typeInterface).As(typeInterface);
                        }
                        if (ii.Single)
                        {
                            registrationBuilder.PropertiesAutowired(new AutowiredPropertySelector())
                                               .PropertiesAutowired(new ResourcePropertySelector())
                                               .SingleInstance();
                        }
                        else
                        {
                            registrationBuilder.PropertiesAutowired(new AutowiredPropertySelector())
                                               .PropertiesAutowired(new ResourcePropertySelector());
                        }
                    }
                    else
                    {
                        var registrationBuilder = builder.RegisterType(ii.ImplementType);
                        foreach (Type typeInterface in ii.InterfaceTypes)
                        {
                            registrationBuilder.Named(ii.Name, typeInterface).As(typeInterface);
                        }
                        if (ii.Single)
                        {
                            registrationBuilder.PropertiesAutowired(new AutowiredPropertySelector())
                                               .PropertiesAutowired(new ResourcePropertySelector())
                                               .SingleInstance();
                        }
                        else
                        {
                            registrationBuilder.PropertiesAutowired(new AutowiredPropertySelector())
                                               .PropertiesAutowired(new ResourcePropertySelector());
                        }
                    }
                }
            }
        }
    }
}